﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Threading;



using MptCodeLibrary;
using MptCodeLibrary.Configuration;
using MptCodeLibrary.Exceptions;
using MptCodeLibrary.TeamFoundation;
using MptCodeLibrary.WcfReceivers;




namespace MptParentChildServiceCmdHost
{
    class Program
    {
        private ServiceHost             mHost_workItemChangedService;
        private WebServiceHost          mHost_MptParentChildReceiver;
        private System.Threading.Timer  mTimer_GlobalListDailyRebuild;
        private System.Threading.Timer  mTimer_RecurringRollup;





        static void Main(string[] args)
        {
            Program p = new Program();


            try
            {

                p.DRIVER_InitializeServices();


                Console.WriteLine("Press ENTER to exit....");
                Console.ReadLine();

            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("Fatal error in command service host: {0}",
                                    ex);

                MptEventLogger.WriteError(sb.ToString());
                Console.WriteLine(sb.ToString());

            }

        } // main





        private void DRIVER_InitializeServices()
        {
            MptInitializer mptInitializer;


            try
            {

                // START THE SERVICE HOSTS SO WE ARE READY FOR INCOMMING MESSAGES
                        mHost_workItemChangedService = new ServiceHost(typeof(WorkItemChangedReceiver));
                        mHost_workItemChangedService.Open();

                        // Using WEB service host so that the service can be remotely invoked from a browser.
                        mHost_MptParentChildReceiver = new WebServiceHost(typeof(MptParentChildReceiver));
                        mHost_MptParentChildReceiver.Open();



                // MAKE SURE WE ARE PROPERLY SUBSCRIBED TO WORK ITEM EVENTS SO GLOBALLISTS CAN BE KEPT UP-TO-DATE
                        mptInitializer = new MptInitializer(new MptConfiguration(), new TeamFoundationFacade());
                        mptInitializer.SubscribeToEvents(mHost_workItemChangedService.BaseAddresses[0].AbsoluteUri);




                // INITIALIZE TIMERS FOR AUTOMATIC RECURRING PROCESSING AT REGULAR TIME INTERVALS

                        // GLOBAL LIST REBUILD TIMER
                                double GlobalListRebuild_WaitTimeTillFirstAutomaticRun_ms;
                                double GlobalListRebuild_RecuranceInterval_ms;

                                GlobalListRebuild_WaitTimeTillFirstAutomaticRun_ms = GetMilliSecondsTill1am();
                                GlobalListRebuild_RecuranceInterval_ms             = TimeSpan.FromTicks(TimeSpan.TicksPerDay).TotalMilliseconds;

                                mTimer_GlobalListDailyRebuild = new System.Threading.Timer(
                                                                                new TimerCallback(TimerAction_GlobalListRebuild), 
                                                                                null,
                                                                                (long)GlobalListRebuild_WaitTimeTillFirstAutomaticRun_ms,
                                                                                (long)GlobalListRebuild_RecuranceInterval_ms);

                     
                        // RECURRING ROLLUP TIMER
                                double Rollup_RecuranceInterval_ms;

                                Rollup_RecuranceInterval_ms = TimeSpan.FromTicks(TimeSpan.TicksPerHour * 3).TotalMilliseconds;
                                mTimer_RecurringRollup = new System.Threading.Timer(
                                                                                new TimerCallback(TimerAction_Rollup),
                                                                                null,
                                                                                (long)Rollup_RecuranceInterval_ms,
                                                                                (long)Rollup_RecuranceInterval_ms);



                Console.WriteLine("Command line service successfully started.");

            }
            catch (Exception ex)
            {

                string errstr;

                errstr = string.Format(CultureInfo.InvariantCulture,
                                       "Unable to successfully initialize the command line services.   Exception: {0}",
                                       ex);

                MptException mex = new MptException(errstr);

                throw mex;
            }


        }   // DRIVER_InitializeServices




        private double GetMilliSecondsTill1am()
        {
            double retval;
            Double milliSecondsPerDay = TimeSpan.FromTicks(TimeSpan.TicksPerDay).TotalMilliseconds;
            Double milliSecondsPerHour = TimeSpan.FromTicks(TimeSpan.TicksPerHour).TotalMilliseconds;

            Double milliSecondsAsOfBegginningOfDay =
                TimeSpan.FromTicks((new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day)).Ticks).
                    TotalMilliseconds;

            Double milliSecondsAsOfNow = TimeSpan.FromTicks(DateTime.Now.Ticks).TotalMilliseconds;


            retval = (milliSecondsPerDay -
                    (milliSecondsAsOfNow - milliSecondsAsOfBegginningOfDay) +
                    milliSecondsPerHour);

            return (retval);
        }





#region TIMER ACTION HANDLERS

        static void TimerAction_GlobalListRebuild(Object state)
        {
            try
            {
                MptEventLogger.WriteTrace(string.Format(CultureInfo.InvariantCulture,
                                                        "Rebuilding this global lists at: {0} {1}",
                                                        DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString()));

                GlobalListBuilder globalListBuilder = new GlobalListBuilder(new MptConfiguration(),
                                                                            new TeamFoundationFacade());

                globalListBuilder.RebuildGlobalListsForProjects();

                MptEventLogger.WriteTrace("Finished with the schedule rebuild of the global list");

            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("Fatal error in command service host while attempting to rebuild global list on recurring schedule: {0}",
                                    ex);

                MptEventLogger.WriteError(sb.ToString());
                Console.WriteLine(sb.ToString());

            }
        }



        static void TimerAction_Rollup(Object state)
        {
            try
            {
                MptEventLogger.WriteTrace(string.Format(CultureInfo.InvariantCulture,
                                            "Rolling up the changed workItems at: {0} {1}",
                                            DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString()));

                WorkItemRollup workItemRollup = new WorkItemRollup(new MptConfiguration());
                int returnValue = workItemRollup.IncrementalProcess();

                if (returnValue > 0)
                    MptEventLogger.WriteError(
                        @"Finished with the schedule rollup of changed work items. There were errors with the rollup.  
                        Check the event viewer for more information.");
                else
                    MptEventLogger.WriteTrace("Finished with the schedule rollup of changed work items");

            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("Fatal error in command service host while attempting to process work rollup on recurring schedule: {0}",
                                    ex);

                MptEventLogger.WriteError(sb.ToString());
                Console.WriteLine(sb.ToString());

            }
        }

#endregion 





    } // class Program





} // namespace MptParentChildServiceCmdHost
